﻿using System;
using System.Collections.Generic;
using DataFiller.DataStorage.Holders;

namespace DataFiller.DataStorage.Interpreters
{
    public delegate object RetrieveModelCallBack(string data);

    public interface IInterpreterContainer
    {
        int Count { get; }
        object TryInterpret(string data);
        void AddInterpreter(IInterpreter interpreter);
    }

    public class InterpreterContainer : IInterpreterContainer
    {
        protected List<IInterpreter> _interpreters;
        protected RetrieveModelCallBack RetrieveModel;

        public int Count
        {
            get { return _interpreters.Count; }
        }

        public InterpreterContainer(RetrieveModelCallBack callback)
        {
            _interpreters = new List<IInterpreter>();
            RetrieveModel = callback;
        }

        #region IInterpreterContainer Members

        public void AddInterpreter(IInterpreter interpreter)
        {
            _interpreters.Add(interpreter);
        }

        /// <summary>
        /// get the appropriate data, by checking whether the parameter is a placeholder,
        /// if it is, we using the expression to retrieve appropriate data from model, then return it.
        /// if not, directly retun null
        /// </summary>
        public virtual object TryInterpret(string data)
        {
            object result = null;
            //step1:
            //when there's no interpreter, we should feed the data directly
            if (Count != 0 && RetrieveModel != null)
            {
                //step2:
                //when need a interpreter, we give the data to this interpreter to check whether it is a placeholder
                Func<object, object> fun = null;
                object model;
                foreach (var interpreter in _interpreters)
                {
                    fun = interpreter.MatchCase(data);
                    if (fun != null)
                    {
                        //step3:
                        //when we get a not null result from the interpreter, 
                        //represents that the given parameter is a recognizable placeholder, 
                        //so  we invoke the retrieve data call back to get the model, 
                        //then using the interpreter result to the model, so that we can get the data that fit the placeholder
                        model = RetrieveModel(data);
                        result = fun(model);
                        break;
                    }
                }
            }

            return result;
        }

        #endregion
    }
}
